package com.ma.a12;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/*
    代理一点都不难，无非就是利用了多态、反射的知识
        1. 方法重写可以增强逻辑，只不过这【增强逻辑】千变万化，不能写死在代理内部
        2. 通过接口回调将【增强逻辑】置于代理类之外
        3. 配合接口方法反射（是多态调用），就可以再联动调用目标方法
        4. 会用 arthas 的 jad 工具反编译代理类
        5. 限制：代理增强是借助多态来实现，因此成员变量、静态方法、final 方法均不能通过代理实现
 */

/**
 * @ClassName A12
 * @Author: mayongqiang
 * @DATE 2022/4/10 12:21
 * @Description: 模拟实现JDK代理 测试类
 */
public class A12 {
    interface Foo {
        void foo();

        int bar();
    }

    /*
    定义一个接口，把代理类的行为抽象出来
     */
    //interface InvocationHandler {
    //    Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    //}

    static class Target implements Foo {

        @Override
        public void foo() {
            System.out.println("target foo");
        }

        @Override
        public int bar() {
            System.out.println("target bar");
            return 100;
        }
    }

    /*
    1、代理类的行为不能写死 ----->  所以将其改为抽象方法  由外部实现它提供具体的操作
    2、在InvocationHandler.invoke中方法不能写死,需要知道当前在调用哪个方法
    3、返回值处理 给invoke定义返回Object
     */
    public static void main(String[] args) {
        Foo proxy = new $Proxy0(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
                //1、功能增强
                System.out.println("before");
                //2、调用目标
                //new Target().foo();
                return method.invoke(new Target(), args);
            }
        });
        proxy.foo();
        int bar = proxy.bar();
        System.out.println(bar);

    }
}
